//实现一个阻塞队列和一个生产者，消费者模型
//创建一个循环队列来实现阻塞队列
class BlockingQueue{
    //队列：头删尾插
    int [] arr=new int [100];
    private int size;//记录数组中有效的元素个数。
    private int head;//头节点
    private int tail;//尾节点
    private  Object lock=new Object();
    private  Object lock1=new Object();
    //入队列
    public   void put(int value) {
        //判断队列是否为满
        synchronized (lock) {
            if (size == arr.length) {
                //队满了要阻塞等待
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            //此时队列不为空
            arr[tail]=value;
            tail++;
            //判断队尾是否到了数组尾巴
            if(tail>=arr.length){
                tail=0;
            }
            size++;
            //完成入队列之后要唤醒出队列的锁
            lock.notify();
        }
    }
    //出队列
    public  Integer take(){
        //判断队列是否为空
        synchronized (lock) {
            if (size == 0) {
                //队列为空，阻塞等待
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            //不为空，出对列
            int val = arr[head];
            head++;
            if (head >= arr.length) {
                head = 0;
            }
            size--;
            //出队列要唤醒入队列的锁
            lock.notify();
            return val;
        }
    }
}
public class ThreadDemo1 {
    public static void main(String[] args) {
        BlockingQueue queue = new BlockingQueue();
        //生产者
        Thread t1 = new Thread(() -> {
            int i=0;
            while (true) {
                System.out.println("生产了" + i);
                queue.put(i);
                i++;
            }
        });
        //消费者
        Thread t2 = new Thread(() -> {
            while (true) {
                try {
                    int num = queue.take();
                    System.out.println("消费了" + num);
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.start();
        t2.start();
    }
}
